package com.StarStudio.Service.Impl;

import cn.hutool.core.util.IdUtil;
import com.StarStudio.DAO.*;
import com.StarStudio.Service.PanicBuyingOrdersService;
import com.ruoyi.common.core.Entity.*;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.domain.SysUser;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class PanicBuyingOrdersServiceImpl implements PanicBuyingOrdersService {

    @Autowired
    PanicBuyingOrdersDAO panicBuyingOrdersDAO;

    @Autowired
    PanicBuyingGoodsDAO panicBuyingGoodsDAO;

    @Autowired
    PanicBuyingCouponsDAO panicBuyingCouponsDAO;

    @Autowired
    RedisService redisService;

    @Autowired
    OrdersDAO ordersDAO;

    @Autowired
    GoodsStockDAO goodsStockDAO;

    @Autowired
    CouponsStockDAO couponsStockDAO;

    @Autowired
    ExchangeDAO exchangeDAO;

    @Autowired
    UserInfoDAO userInfoDAO;

    @Autowired
    GoodsDAO goodsDAO;

    @Autowired
    BeansActionDAO beansActionDAO;

    @Autowired
    CouponsDAO couponsDAO;

    @Resource
    RedissonClient redissonClient;


    @Override
    public List<PanicBuyingOrders> findPanicBuyingOrdersList(PanicBuyingOrders panicBuyingOrders) {
        SysUser sysUser = SecurityUtils.getLoginUser().getSysUser();
        List<PanicBuyingOrders> panicBuyingOrdersList;
        if (sysUser.isAdmin()){
            panicBuyingOrdersList = panicBuyingOrdersDAO.findPanicBuyingOrdersList(panicBuyingOrders);
        }else {
            panicBuyingOrdersList = panicBuyingOrdersDAO.findStorePanicBuyingOrdersList(panicBuyingOrders,sysUser.getUserId());
        }
        if (panicBuyingOrdersList != null && panicBuyingOrdersList.size() > 0){
            for (PanicBuyingOrders buyingOrders : panicBuyingOrdersList) {
                Map<String,Object> param = new HashMap<>();
                if (buyingOrders.getGoods_id() != null && buyingOrders.getGoods_id() > 0){
                    Goods goods = goodsDAO.findByGoods_id(buyingOrders.getGoods_id());
                    param.put("goodsName",goods.getGoods_name());
                }else {
                    Coupons coupons = couponsDAO.findByCoupon_id(buyingOrders.getCoupons_id());
                    param.put("couponsName",coupons.getCoupon_name());
                }
                Orders byOrder_id = ordersDAO.findByOrder_id(buyingOrders.getOrder_id());
                param.put("orderTime",byOrder_id.getOrder_time());
                UserInfo userInfo = userInfoDAO.findByUser_id(buyingOrders.getUser_id());
                param.put("userName",userInfo.getReal_name());
                buyingOrders.setParams(param);
            }
        }
        return panicBuyingOrdersList;
    }

    @Override
    public long findTotalRecord() {
        return panicBuyingOrdersDAO.findTotalRecord();
    }

    /**
     * 真正生成订单
     * @param orders 订单对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void NewPanicBuyingOrders(Orders orders) throws InterruptedException {
        redisService.increment("countThreads");
        //Redis分布式锁
        RLock lock = redissonClient.getLock("Lock:PanicBuyingOrders:" + orders.getGoods_id());
        //尝试获取锁
        boolean isLock = lock.tryLock(60, 60, TimeUnit.SECONDS);
//        boolean isLock = lock.tryLock(1, 22, TimeUnit.SECONDS);
//        boolean isLock = lock.tryLock();
//        boolean isLock = lock.tryLock();
//        lock.lock();
        //判断是否获取成功
        if (isLock){
            redisService.increment("countLock");
            try {
                if (orders.getGoods_id() != null && orders.getGoods_id() > 0){ /* 实体商品 */
                    if (redisService.hasKey("isPBGoodsStockEmpty:" + orders.getGoods_id())){ //库存为空
                        return;
                    }
                    //拿到抢购商品对象
                    PanicBuyingGoods panicBuyingGoods = panicBuyingGoodsDAO.findByGoods_id(orders.getGoods_id());
                    List<GoodsStock> unsoldItems = goodsStockDAO.findUnsoldItems(orders.getGoods_id(), false);
                    if (panicBuyingGoods.getPanic_buying_goods_stock() >= 1 && unsoldItems.size() > 0){ //解决库存超卖 
                        //panicBuyingGoods.setPanic_buying_goods_stock(panicBuyingGoods.getPanic_buying_goods_stock() - 1);
                        //int i = panicBuyingGoodsDAO.updatePanicBuyingGoods(panicBuyingGoods);
                        int i = panicBuyingGoodsDAO.reduceStock(panicBuyingGoods);
                        if (i == 0){  //用户执行减库存的操作失败了，但是依然会去执行下订单的操作，这样就产生了生成的订单数大于卖出的商品数的问题
                            //Long count = redisService.increment("count");
                            return; //解决办法：判断 update语句是否执行成功，如果未执行成功，直接返回
                            // 注意：mybatis的update语句默认返回匹配的行数，而不是影响的行数，故在jdbc的 URL上加 &useAffectedRows=true
                        }else {
                            //redisService.increment("count1");
                            //往订单表写入数据
                            orders.setOrder_status(MessageConstant.ORDER_ALREADY_PAID);//更新订单状态
                            orders.setOrder_time(new Timestamp(new Date().getTime())); //添加下单时间
                            orders.setDel_flag(false);
                            orders.setOrder_id(IdUtil.getSnowflakeNextId()); //使用雪花ID
                            ordersDAO.orderAdd(orders);
                            //往 GoodsStock中更新数据
//                            List<GoodsStock> unsoldItems1 = goodsStockDAO.findUnsoldItems(orders.getGoods_id(), false);
//                            GoodsStock goodsStock = unsoldItems1.get(0);
//                            GoodsStock goodsStock = goodsStockDAO.findSoldItem(orders.getGoods_id(), false);
//                            goodsStock.setHave_been_sold(true);
//                            goodsStock.setSold_order_id(orders.getOrder_id());
//                            goodsStock.setSold_time(new Timestamp(new Date().getTime()));
                            goodsStockDAO.updateGoodsStockByOrder(orders.getOrder_id(), orders.getGoods_id());
                            //redisService.increment("count2");
                            // 往 Exchange中更新数据
                            GoodsStock goodsStock = goodsStockDAO.findGoodsStockByGoodsIdAndOrderId(orders.getGoods_id(), orders.getOrder_id());
                            Exchange exchange = new Exchange();
                            exchange.setGoods_id(orders.getGoods_id());
                            exchange.setStore_id(orders.getStore_id());
                            exchange.setExchange_status(MessageConstant.EXCHANGE_STATUS_USED);
                            exchange.setOrder_id(orders.getOrder_id());
                            exchange.setExchange_user_id(orders.getOrder_user_id());
                            exchange.setGoods_item_id(goodsStock.getItem_id());
                            exchange.setUse_time(new Timestamp(new Date().getTime()));
                            exchange.setExchange_id(IdUtil.getSnowflakeNextId()); //使用雪花ID
                            exchangeDAO.addExchange(exchange);
                            //往抢购订单表写入数据
                            PanicBuyingOrders panicBuyingOrders = new PanicBuyingOrders();
                            panicBuyingOrders.setUser_id(orders.getOrder_user_id());
                            panicBuyingOrders.setGoods_id(orders.getGoods_id());
                            panicBuyingOrders.setOrder_id(orders.getOrder_id());
                            panicBuyingOrders.setPanic_buying_order_id(IdUtil.getSnowflakeNextId()); //使用雪花ID
                            panicBuyingOrders.setDel_flag(false);
                            panicBuyingOrdersDAO.addPB_order(panicBuyingOrders);
                            //往 UserInfo中更新数据
                            UserInfo byUser_id = userInfoDAO.findByUser_id(orders.getOrder_user_id());
                            int panic_buying_price = panicBuyingGoods.getPanic_buying_price();
                            if (byUser_id.getBeans_spend_day() != null){
                                byUser_id.setBeans_spend_day(byUser_id.getBeans_spend_day() + panic_buying_price);//更新该用户今天消费的鲜豆数
                            }else {
                                byUser_id.setBeans_spend_day(panic_buying_price);
                            }
                            if (byUser_id.getBeans_spend_total() != null){
                                byUser_id.setBeans_spend_total(byUser_id.getBeans_spend_total() + panic_buying_price);//更新该用户消费的总鲜豆数
                            }else {
                                byUser_id.setBeans_spend_total(panic_buying_price);
                            }
                            byUser_id.setBeans(byUser_id.getBeans() - panic_buying_price);//扣除后更新用户拥有的鲜豆
                            userInfoDAO.updateUserInfo(byUser_id);
                            //往 BeansAction中更新数据
                            BeansAction beansAction = new BeansAction();
                            Goods byGoods_id = goodsDAO.findByGoods_id(orders.getGoods_id());
                            beansAction.setBeans_action_describe("兑换" + byGoods_id.getGoods_name());
                            beansAction.setBeans_action_number(- panic_buying_price);
                            beansAction.setBeans_action_type(MessageConstant.BEANS_EXPEND);
                            beansAction.setBeans_action_time(new Timestamp(new Date().getTime()));
                            beansAction.setBeans_action_user_id(orders.getOrder_user_id());
                            beansAction.setBeans_action_id(IdUtil.getSnowflakeNextId()); //使用雪花ID
                            beansActionDAO.addBeansAction(beansAction);
                            // 向省平台发送请求更新用户鲜豆
                            //HttpRequestUtils.ProvinceSystemBeanAction(orders.getOrder_user_id(),- panic_buying_price);
                            redisService.setCacheObject("panic_buying_goods_order:" + orders.getOrder_user_id() + ":" + orders.getGoods_id(), panicBuyingOrders);
                        }
                    }else {
                        //如果没有库存 在 Redis中进行标记（有key即可）
                        redisService.setCacheObject("isPBGoodsStockEmpty:" + orders.getGoods_id(),0);
                        return;
                    }
                } else if (orders.getCoupons_id() != null && orders.getCoupons_id() > 0) { /* 优惠券 */
                    if (redisService.hasKey("isPBCouponsStockEmpty" + orders.getCoupons_id())){ //库存为空
                        return;
                    }
                    //拿到抢购优惠券对象
                    PanicBuyingCoupons panicBuyingCoupons = panicBuyingCouponsDAO.findByCoupons_id(orders.getCoupons_id());
                    List<CouponsStock> unsoldItems = couponsStockDAO.findUnsoldItems(orders.getCoupons_id(), false);
                    if (panicBuyingCoupons.getPanic_buying_coupons_stock() >= 1 && unsoldItems.size() > 0){ //解决库存超卖
//                        panicBuyingCoupons.setPanic_buying_coupons_stock(panicBuyingCoupons.getPanic_buying_coupons_stock() - 1);
//                        int i = panicBuyingCouponsDAO.updatePanicBuyingCoupons(panicBuyingCoupons);
                        int i = panicBuyingCouponsDAO.reduceStock(panicBuyingCoupons);
                        if (i == 0){  //用户执行减库存的操作失败了，但是依然会去执行下订单的操作，这样就产生了生成的订单数大于卖出的商品数的问题
                            return; //解决办法：判断 update语句是否执行成功，如果未执行成功，直接返回
                            // 注意：mybatis的update语句默认返回匹配的行数，而不是影响的行数，故在jdbc的URL上加 &useAffectedRows=true
                        }else {
                            //往订单表写入数据
                            orders.setOrder_status(MessageConstant.ORDER_FINISHED);//更新订单状态
                            orders.setOrder_time(new Timestamp(new Date().getTime())); //添加下单时间
                            orders.setDel_flag(false);
                            orders.setOrder_id(IdUtil.getSnowflakeNextId()); //使用雪花ID
                            ordersDAO.orderAdd(orders);
                            //往 CouponsStock中更新数据
//                            CouponsStock couponsStock = unsoldItems.get(0);
//                            couponsStock.setHave_been_sold(true);
//                            couponsStock.setSold_order_id(orders.getOrder_id());
//                            couponsStock.setSold_time(new Timestamp(new Date().getTime()));
//                            couponsStockDAO.updateCouponsStock(couponsStock);
                            couponsStockDAO.updateCouponsStockByOrder(orders.getOrder_id(), orders.getCoupons_id());
                            // 往 Exchange中更新数据
                            CouponsStock couponsStock = couponsStockDAO.findCouponsStockByCouponsIdAndOrderId(orders.getCoupons_id(), orders.getOrder_id());
                            Exchange exchange = new Exchange();
                            exchange.setCoupons_id(orders.getCoupons_id());
                            exchange.setStore_id(orders.getStore_id());
                            exchange.setExchange_status(MessageConstant.EXCHANGE_STATUS_EXCHANGED_BUT_NOT_USED);
                            exchange.setOrder_id(orders.getOrder_id());
                            exchange.setExchange_user_id(orders.getOrder_user_id());
                            exchange.setCoupons_item_id(couponsStock.getItem_id());
                            exchange.setUse_time(new Timestamp(new Date().getTime()));
                            exchange.setExchange_id(IdUtil.getSnowflakeNextId()); //使用雪花ID
                            exchangeDAO.addExchange(exchange);
                            //往抢购订单表写入数据
                            PanicBuyingOrders panicBuyingOrders = new PanicBuyingOrders();
                            panicBuyingOrders.setUser_id(orders.getOrder_user_id());
                            panicBuyingOrders.setCoupons_id(orders.getCoupons_id());
                            panicBuyingOrders.setOrder_id(orders.getOrder_id());
                            panicBuyingOrders.setPanic_buying_order_id(IdUtil.getSnowflakeNextId()); //使用雪花ID
                            panicBuyingOrders.setDel_flag(false);
                            panicBuyingOrdersDAO.addPB_order(panicBuyingOrders);
                            //往 UserInfo中更新数据
                            UserInfo byUser_id = userInfoDAO.findByUser_id(orders.getOrder_user_id());
                            Coupons byCoupon_id = couponsDAO.findByCoupon_id(panicBuyingCoupons.getCoupons_id());
                            double market_price = byCoupon_id.getMarket_price();
                            int panic_buying_price = panicBuyingCoupons.getPanic_buying_price();
                            if (byUser_id.getBeans_spend_day() != null){
                                byUser_id.setBeans_spend_day(byUser_id.getBeans_spend_day() + panic_buying_price);//更新该用户今天消费的鲜豆数
                            }else {
                                byUser_id.setBeans_spend_day(panic_buying_price);
                            }
                            if (byUser_id.getBeans_spend_total() != null){
                                byUser_id.setBeans_spend_total(byUser_id.getBeans_spend_total() + panic_buying_price);//更新该用户消费的总鲜豆数
                            }else {
                                byUser_id.setBeans_spend_total(panic_buying_price);
                            }
                            if (byUser_id.getCoupons_spend_day() != null){
                                byUser_id.setCoupons_spend_day(byUser_id.getCoupons_spend_day() + orders.getNumber());//更新该用户今天消费的优惠券数量
                            }else {
                                byUser_id.setCoupons_spend_day(orders.getNumber());
                            }
                            if (byUser_id.getCoupons_value_spend_day() != null){
                                byUser_id.setCoupons_value_spend_day(byUser_id.getCoupons_value_spend_day() + market_price * orders.getNumber());//更新该用户今天消费的优惠券总额度
                            }else {
                                byUser_id.setCoupons_value_spend_day(market_price * orders.getNumber());
                            }
                            if (byUser_id.getCoupons_spend_total() != null){
                                byUser_id.setCoupons_spend_total(byUser_id.getCoupons_spend_total() + orders.getNumber());//更新该用户在商城消费的总优惠券数量
                            }else {
                                byUser_id.setCoupons_spend_total(orders.getNumber());
                            }
                            byUser_id.setCoupons_value_spend_total(byUser_id.getCoupons_spend_total() + market_price * orders.getNumber());//更新该用户在商城消费的优惠券总额度
                            byUser_id.setBeans(byUser_id.getBeans() - panic_buying_price);//扣除后更新用户拥有的鲜豆
                            userInfoDAO.updateUserInfo(byUser_id);
                            //往 BeansAction中更新数据
                            BeansAction beansAction = new BeansAction();
                            Coupons coupons = couponsDAO.findByCoupon_id(orders.getCoupons_id());
                            beansAction.setBeans_action_describe("兑换" + coupons.getCoupon_name());
                            beansAction.setBeans_action_number(- panic_buying_price);
                            beansAction.setBeans_action_type(MessageConstant.BEANS_EXPEND);
                            beansAction.setBeans_action_time(new Timestamp(new Date().getTime()));
                            beansAction.setBeans_action_user_id(orders.getOrder_user_id());
                            beansAction.setBeans_action_id(IdUtil.getSnowflakeNextId()); //使用雪花ID
                            beansActionDAO.addBeansAction(beansAction);
                            // 向省平台发送请求更新用户鲜豆
                            //HttpRequestUtils.ProvinceSystemBeanAction(orders.getOrder_user_id(),- panic_buying_price);
                            redisService.setCacheObject("panic_buying_coupons_order:" + orders.getOrder_user_id() + ":" + orders.getCoupons_id(),panicBuyingOrders);
                        }
                    }else {
                        //如果没有库存 在 Redis中进行标记（有key即可）
                        redisService.setCacheObject("isPBCouponsStockEmpty" + orders.getCoupons_id(),0);
                        return;
                    }
                }
            }finally {
                //释放锁
                lock.unlock();
            }
        }
    }

    /**
     * 获取订单ID（判断抢购是否成功）
     * @param user_id  用户ID
     * @param type 类型（商品还是优惠券）
     * @param thingsId 商品ID或优惠券ID
     * @return 订单ID
     * @Author ChengLee
     * @Date 2023/01/08
     */
    @Override
    public Long findOrderIdByCondition(long user_id, int type, long thingsId) {
        Long orderId = null;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        if (type == 1){
            orderId = panicBuyingOrdersDAO.findPanicBuyingGoodsOrderId(user_id,thingsId, sdf.format(new Date()));
        } else if (type == 2) {
            orderId = panicBuyingOrdersDAO.findPanicBuyingCouponsOrderId(user_id,thingsId,sdf.format(new Date()));
        }
        return orderId;
    }

    @Override
    public long findStoreTotalRecord(Long userId) {
        return panicBuyingOrdersDAO.findStoreTotalRecord(userId);
    }

    @Override
    public List<PanicBuyingOrders> findPanicBuyingGoodsOrdersList(PanicBuyingOrders panicBuyingOrders) {
        SysUser sysUser = SecurityUtils.getLoginUser().getSysUser();
        List<PanicBuyingOrders> panicBuyingOrdersList;
        if (sysUser.isAdmin()){
            panicBuyingOrdersList = panicBuyingOrdersDAO.findPanicBuyingGoodsOrdersList(panicBuyingOrders);
        }else {
            panicBuyingOrdersList = panicBuyingOrdersDAO.findStorePanicBuyingGoodsOrdersList(panicBuyingOrders,sysUser.getUserId());
        }
        if (panicBuyingOrdersList != null && panicBuyingOrdersList.size() > 0){
            for (PanicBuyingOrders buyingOrders : panicBuyingOrdersList) {
                Map<String,Object> param = new HashMap<>();
                if (buyingOrders.getGoods_id() != null && buyingOrders.getGoods_id() > 0){
                    Goods goods = goodsDAO.findByGoods_id(buyingOrders.getGoods_id());
                    param.put("goodsName",goods.getGoods_name());
                }else {
                    Coupons coupons = couponsDAO.findByCoupon_id(buyingOrders.getCoupons_id());
                    param.put("couponsName",coupons.getCoupon_name());
                }
                Orders byOrder_id = ordersDAO.findByOrder_id(buyingOrders.getOrder_id());
                param.put("orderTime",byOrder_id.getOrder_time());
                UserInfo userInfo = userInfoDAO.findByUser_id(buyingOrders.getUser_id());
                param.put("userName",userInfo.getReal_name());
                buyingOrders.setParams(param);
            }
        }
        return panicBuyingOrdersList;
    }

    @Override
    public long findPanicBuyingGoodsOrdersTotalRecord() {
        return panicBuyingOrdersDAO.findPanicBuyingGoodsOrdersTotalRecord();
    }

    @Override
    public long findStorePanicBuyingGoodsOrdersTotalRecord(Long storeId) {
        return panicBuyingOrdersDAO.findStorePanicBuyingGoodsOrdersTotalRecord(storeId);
    }

    @Override
    public List<PanicBuyingOrders> findPanicBuyingCouponsOrdersList(PanicBuyingOrders panicBuyingOrders) {
        SysUser sysUser = SecurityUtils.getLoginUser().getSysUser();
        List<PanicBuyingOrders> panicBuyingOrdersList;
        if (sysUser.isAdmin()){
            panicBuyingOrdersList = panicBuyingOrdersDAO.findPanicBuyingCouponsOrdersList(panicBuyingOrders);
        }else {
            panicBuyingOrdersList = panicBuyingOrdersDAO.findStorePanicBuyingCouponsOrdersList(panicBuyingOrders,sysUser.getUserId());
        }
        if (panicBuyingOrdersList != null && panicBuyingOrdersList.size() > 0){
            for (PanicBuyingOrders buyingOrders : panicBuyingOrdersList) {
                Map<String,Object> param = new HashMap<>();
                if (buyingOrders.getGoods_id() != null && buyingOrders.getGoods_id() > 0){
                    Goods goods = goodsDAO.findByGoods_id(buyingOrders.getGoods_id());
                    param.put("goodsName",goods.getGoods_name());
                }else {
                    Coupons coupons = couponsDAO.findByCoupon_id(buyingOrders.getCoupons_id());
                    param.put("couponsName",coupons.getCoupon_name());
                }
                Orders byOrder_id = ordersDAO.findByOrder_id(buyingOrders.getOrder_id());
                param.put("orderTime",byOrder_id.getOrder_time());
                UserInfo userInfo = userInfoDAO.findByUser_id(buyingOrders.getUser_id());
                param.put("userName",userInfo.getReal_name());
                buyingOrders.setParams(param);
            }
        }
        return panicBuyingOrdersList;
    }

    @Override
    public long findPanicBuyingCouponsOrdersTotalRecord() {
        return panicBuyingOrdersDAO.findPanicBuyingCouponsOrdersTotalRecord();
    }

    @Override
    public long findStorePanicBuyingCouponsOrdersTotalRecord(Long storeId) {
        return panicBuyingOrdersDAO.findStorePanicBuyingCouponsOrdersTotalRecord(storeId);
    }

    @Override
    public List<Long> findUserIdListByGoodsId(Long panicBuyingGoodsId) {
        return panicBuyingOrdersDAO.findUserIdListByGoodsId(panicBuyingGoodsId);
    }

    @Override
    public List<Long> findUserIdListByCouponsId(Long couponsId) {
        return panicBuyingOrdersDAO.findUserIdListByCouponsId(couponsId);
    }


}
